/*
 * utility functions
 * $Id: util.c,v 1.4 2012/06/28 09:53:36 curt Exp $
 */

#include <stdio.h>

void
assert_fail(char *str)
{
    fprintf(stderr, "assfail: %s\n", str);
    fflush(stderr);
    exit(-99);
}char hexbyte[] = "0123456789abcdef";

#define MAXBYTES 16
#define HEXSTART 14
#define ASCIISTART 68
#define iHEX(i)		((i * 3) + (i / 4) + HEXSTART)
#define iASCII(i)	(ASCIISTART + i)

void
clearline(char *lb, int len)
{
    while (len-- > 1) {
        *lb++ = ' ';
    }
    *lb = '\0';
}

void
setaddr(char *buf, unsigned int offset) {
    int i;

    for (i = 0; i < 8; i++) {
        buf[i + 2] = hexbyte[(offset >> (4 * (7 - i))) & 0xf];
    }
    buf[2+9] = ':';
}

void
dump_bytes(unsigned char *buf, int offset, int len)
{
    int i;
    char linebuf[160];
    unsigned char c;
    int index;

    if (!buf)
        return;

    clearline(linebuf, sizeof(linebuf));
    index = 0;

    setaddr(linebuf, offset);

    while (len--) {
        c = buf[offset++];
        linebuf[iHEX(index)] = hexbyte[(c >> 4) & 0xf];
		linebuf[iHEX(index)+1] = hexbyte[c & 0xf];
		linebuf[iHEX(index)+2] = ' ';
		linebuf[iASCII(index)] = (c < ' ' || c > 0x7e) ? '.' : c;
		linebuf[iASCII(index)+1] = '\0';
		if (++index == MAXBYTES) {
            if (index) {
                puts(linebuf);
                clearline(linebuf, sizeof(linebuf));
                setaddr(linebuf, offset);
                index = 0;
            }
		}
	}
    if (index) {
        puts(linebuf);
    }
}

/*
 * sign-extend an integer
 */
int
extend(int val, int bits) {
	int ret;

	if (val >> (bits - 1)) {
		ret = (-2 << (bits - 1)) | val;
	} else {
		ret = val;
	}
	return ret;
}

/*
 * dump out a binary with variable bit boundaries
 * breakbits: output a space after all set bits .
 * it's safe to call multiple times
 */
#define PINGPONG 4
char *
format_binary(unsigned int val, int bits, unsigned int breakbits)
{
    static unsigned char pingpong = 0;
	static char buf[65 * PINGPONG];
	char *rb, *p;
	int i;

	if (bits > 32) bits = 32;

	rb = p = &buf[65 * pingpong++];
    pingpong %= PINGPONG;

	for (i = bits - 1; i >= 0; i--) {
		if (val & (1 << i)) {
			*p++ = '1';
		} else {
			*p++ = '0';
		}
		if (breakbits & (1 << i)) {
			*p++ = ' ';
		}
	}
	*p = '\0';
	return rb;
}
